// This is the main DLL file.

#include "stdafx.h"

#include "MemoryReader.h"

namespace DarkBone {

MemoryReader::MemoryReader() {};
MemoryReader::~MemoryReader() {};

Boolean MemoryReader::GetProcess(String^ processName, Int32% processId) {
	cli::array<Process^> ^zProcesses = Process::GetProcessesByName(processName);
	Int64 iMax = 0;
	Int32 index = 0;
	for (Int32 i = 0; i < zProcesses->Length; i++) {
		if (zProcesses[i]->VirtualMemorySize64 > iMax) {
			iMax = zProcesses[i]->VirtualMemorySize64;
			index = i;
		}
	}
	if (zProcesses->Length <= 0) {
		return false;
	} else {
		processId = zProcesses[index]->Id;
		this->m_process = zProcesses[index];
	}
	return true;
}

Boolean MemoryReader::ReadMemory(IntPtr pAddress, cli::array<Byte>^ bzBytes) {
	Int32 iLength = bzBytes->Length;
	SIZE_T iBytesRead = 0;
	byte *bytes = new byte[iLength];
	BOOL bResult = ReadProcessMemory((HANDLE)this->m_process->Handle, (LPCVOID)pAddress, (LPVOID)bytes, iLength, &iBytesRead);
	if ((iLength != iBytesRead) || (!bResult)) {
		return false;
	}
	while (--iLength >= 0) {
		bzBytes[iLength] = bytes[iLength];
	}
	delete [] bytes;
	return (bResult)?true:false;
}

Boolean MemoryReader::ReadMemoryInt32(IntPtr pAddress, Int32% value) {
	SIZE_T iBytesRead = 0;
	byte *bytes = new byte[4];
	BOOL bResult = ReadProcessMemory((HANDLE)this->m_process->Handle, (LPCVOID)pAddress, (LPVOID)bytes, 4, &iBytesRead);
	if ((4 != iBytesRead) || (!bResult)) {
		return false;
	}
	value = (*bytes) | (*(bytes + 1) << 8)  | (*(bytes + 2) << 16) | (*(bytes + 3) << 24);
	delete [] bytes;
	return (bResult)?true:false;
}

Boolean MemoryReader::ReadMemoryInt16(IntPtr pAddress, Int16% value) {
	SIZE_T iBytesRead = 0;
	byte *bytes = new byte[2];
	BOOL bResult = ReadProcessMemory((HANDLE)this->m_process->Handle, (LPCVOID)pAddress, (LPVOID)bytes, 2, &iBytesRead);
	if ((2 != iBytesRead) || (!bResult)) {
		return false;
	}
	value = Int16((*bytes) | (*(bytes + 1) << 8));
	delete [] bytes;
	return (bResult)?true:false;
}

Boolean MemoryReader::ReadMemory(IntPtr pAddress, Byte% value) {
	SIZE_T iBytesRead = 0;
	byte *bytes = new byte[1];
	BOOL bResult = ReadProcessMemory((HANDLE)this->m_process->Handle, (LPCVOID)pAddress, (LPVOID)bytes, 1, &iBytesRead);
	if ((1 != iBytesRead) || (!bResult)) {
		return false;
	}
	value = (*bytes);
	delete [] bytes;
	return (bResult)?true:false;
}

Boolean MemoryReader::ReadMemory(IntPtr pAddress, String^ %string) {
	SIZE_T iBytesRead = 0;
	byte *bytes = new byte[1];
	Int32 i = 0;
	string = String::Empty;
	BOOL bResult = FALSE;
	do {
		bResult = ReadProcessMemory((HANDLE)this->m_process->Handle, (LPCVOID)(pAddress.ToInt32() + i), (LPVOID)bytes, 1, &iBytesRead);
		if ((1 != iBytesRead) || (!bResult)) {
			return false;
		}
		if (bytes[0] != 0) {
			string += (Char)bytes[0];
		}
		i++;
	} while (bytes[0] != 0);
	delete [] bytes;
	return true;
}

Boolean MemoryReader::WriteMemory(IntPtr pAddress, Byte% value) {
	SIZE_T iBytesWritten = 0;
	byte *bytes = new byte[1];
	BOOL bResult = WriteProcessMemory((HANDLE)this->m_process->Handle, (LPVOID)pAddress, (LPVOID)bytes, 1, &iBytesWritten);
	if ((1 != iBytesWritten) || (!bResult)) {
		return false;
	}
	value = (*bytes);
	delete [] bytes;
	return (bResult)?true:false;
}

String^ MemoryReader::GetSC2ProcessVersion() {
	if (this->m_process) {
		return this->m_process->MainModule->FileVersionInfo->FileVersion;
	} else {
		return "Process not running";
	}
}


}
